﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Net5ApiAndEfMySql.DtoModel;
using Net5ApiAndEfMySql.DtoModel.SystemAdmin;
using Net5ApiAndEfMySql.IRepository.SystemAdmin;
using Net5ApiAndEfMySql.IService.SystemAdmin;
using Net5ApiAndEfMySql.PoModel.SystemAdmin;
using Net5CommonLib.SystemLib.Common;
using Net5CommonLib.SystemLib.Tools.TextTools;
using Net5CommonLib.SystemLib.TypeTools;
using VueAndNetCoreEfApi.PoModel.SystemAdmin;

namespace Net5ApiAndEfMySql.Service.SystemAdmin
{
    public class OperatorService : BaseService, IOperatorService
    {
        private int expireUserTokenRedisSecond = 2000; //存用户token的redis过期时间,以秒为单位
        public int expireTokenSecond = 1400;  //token过期时间
        private IOperatorRepository _iOperatorRepository;
        private string adminUserDtoRedisKey = "saveAdminUserDtoRedisKey";
        public OperatorService(IOperatorRepository iOperatorRepository)
        {
            _iOperatorRepository = iOperatorRepository;
        }


        #region 系统方法
        public OperatorPo GetAdminUserByUserName(string userName)
        {
            return _iOperatorRepository.GetAdminUserByUserName(userName);
        }

        public OperatorDto Login(string userName, string pwd, ClientType clientType, out string mess)
        {
            mess = "";
            if (string.IsNullOrEmpty(userName))
            {
                mess = "用户名参数错误";
                return null;
            }
            if (string.IsNullOrEmpty(pwd))
            {
                mess = "密码参数错误";
                return null;
            }
            if (!Enum.IsDefined(typeof(ClientType), clientType))
            {
                mess = "客户端类型不正确";
                return null;
            }
            OperatorPo adminUser = GetAdminUserByUserName(userName);
            if (adminUser == null)
            {
                mess = "用户名错误";
                return null;
            }
            if (adminUser.op_pwd.ToLower() != StringMd5.Md5Hash32Salt(pwd).ToLower())
            {
                mess = "用户名或密码错误";
                return null;
            }
            if (adminUser.op_state == 0)
            {
                mess = "用户无权登录";
                return null;
            }

            OperatorDto adminUserDto = IniUserAndToken(adminUser, clientType);
            mess = "登录成功!";
            return adminUserDto;
        }
        /// <summary>
        /// 获取token
        /// </summary>
        /// <param name="adminUserPo">用户</param>
        /// <param name="clientType">客户端类型</param>
        /// <returns></returns>
        public OperatorDto IniUserAndToken(OperatorPo adminUserPo, ClientType clientType)
        {
            //声明用于生成token的对象
            SimpleTokenInfo simpleTokenInfo = new SimpleTokenInfo();
            simpleTokenInfo.UserName = adminUserPo.op_account;
            simpleTokenInfo.ClientType = clientType;
            string token = JwtUtil.Encode(simpleTokenInfo); //加密生成token
            OperatorDto userAndTokenDto = new OperatorDto();
            ModelCopier.CopyModel(adminUserPo, userAndTokenDto);
            TokenInfo tokenInfo = new TokenInfo();
            tokenInfo.Token = token;
            tokenInfo.ExpireTime = DateTime.Now.AddSeconds(expireTokenSecond);
            RedisManager.HSet(simpleTokenInfo.UserName, clientType.ToString(), tokenInfo);
            RedisManager.HSet(simpleTokenInfo.UserName, adminUserDtoRedisKey, userAndTokenDto, expireUserTokenRedisSecond);
            userAndTokenDto.Token = token;
            return userAndTokenDto;

        }


        /// <summary>
        /// 验证token是否有效
        /// </summary>
        /// <param name="token"></param>
        /// <returns></returns>
        public ResultCode ValidateToken(string token)
        {
            if (GetUserInRedisByToken(token) != null) return ResultCode.Ok;
            return ResultCode.NoLogin;
        }
        /// <summary>
        /// 用token在Resids缓存中获取用户,返回Null代表token无效
        /// </summary>
        /// <param name="token">token</param>
        /// <returns></returns>
        public OperatorDto GetUserInRedisByToken(string token)
        {
            SimpleTokenInfo simpleTokenInfo = DecodeToken(token);
            if (simpleTokenInfo == null) return null;
            TokenInfo tokenInfo = RedisManager.HGet<TokenInfo>(simpleTokenInfo.UserName, simpleTokenInfo.ClientType.ToString());

            if (tokenInfo != null)
            {
                //判断token是否一致,
                //因为同一用户名可能用不同的相同设备登录,所以造成token不一致,要验证token
                if (tokenInfo.Token.Equals(token) && (tokenInfo.ExpireTime - DateTime.Now).TotalSeconds > 0)
                {
                    //刷新时间,这样每次请求接口,都会把过期时间调整为最初时间
                    tokenInfo.ExpireTime = DateTime.Now.AddSeconds(expireTokenSecond);
                    //将最新的token过期时间更新到 redis中
                    RedisManager.HSet(simpleTokenInfo.UserName, simpleTokenInfo.ClientType.ToString(), tokenInfo);

                    OperatorDto adminUserDto = RedisManager.HGet<OperatorDto>(simpleTokenInfo.UserName, adminUserDtoRedisKey);
                    //刷新对应redis的过期时间
                    RedisManager.Expire(simpleTokenInfo.UserName, expireUserTokenRedisSecond);
                    adminUserDto.Token = token;
                    return adminUserDto;
                }
                return null;
            }
            return null;
        }
        /// <summary>
        /// 解密token
        /// </summary>
        /// <param name="token"></param>
        /// <returns></returns>
        public SimpleTokenInfo DecodeToken(string token)
        {
            if (string.IsNullOrEmpty(token)) return null;
            return JwtUtil.Decode<SimpleTokenInfo>(token);
        }

        /// <summary>
        /// 获取与token对应的登录用户信息
        /// </summary>
        /// <param name="token">token</param>
        /// <returns></returns>
        public OperatorDto GetLoginUserByToken(string token)
        {
            SimpleTokenInfo tokenInfo = DecodeToken(token);
            if (tokenInfo == null) return null;
            OperatorDto adminUserDto = RedisManager.HGet<OperatorDto>(tokenInfo.UserName, adminUserDtoRedisKey);

             adminUserDto.Token = token;
            return adminUserDto;
        }


        // 退出登录
        public bool LoginOut(string token)
        {
            SimpleTokenInfo tokenInfo = DecodeToken(token);
            if (tokenInfo == null) return false;
            return RedisManager.HRemove(tokenInfo.UserName, tokenInfo.ClientType.ToString());
        }

        public bool ValidateUserName(string userName)
        {
            if (GetAdminUserByUserName(userName) != null) return false;
            return true;
        }

        public OperatorDto GetAdminUserDtoByUserName(string userName)
        {
            return _iOperatorRepository.GetAdminUserDtoByUserName(userName);
        }
        #endregion


        //操作员显示
        public PagerResult<OperatorDto> GetPageList(SearchModel m)
        {
            return _iOperatorRepository.GetPageList(m);
        }
        //操作员添加
        public bool AddOperator(OperatorDto obj)
        {
            if (!ValidateOperatorByAccount(obj.op_account)) return false; //验证账户是否唯一
            if(!ValidateOperatorByCard(obj.op_card)) return false; //验证编号是否唯一
            obj.op_createtime = DateTime.Now;
            obj.op_pwd = StringMd5.Md5Hash32Salt(obj.op_pwd);
            return _iOperatorRepository.AddOperator(obj);
        }
        //操作员修改
        public bool UptOperator(OperatorDto obj)
        {
            return _iOperatorRepository.UptOperator(obj);
        }
        //操作员状态修改
        public bool UptStateByCard(string card)
        {
            return _iOperatorRepository.UptStateByCard(card);
        }
        //操作员删除
        public bool DelOperator(string card)
        {
            return _iOperatorRepository.DelOperator(card);
        }
        //操作员批量删除
        public bool DelOperatorList(string keys)
        {
            return _iOperatorRepository.DelOperatorList(keys);
        }
        //操作员获取
        public OperatorPo GetOperatorByCard(string card)
        {
            return _iOperatorRepository.GetOperatorByCard(card);
        }
        //唯一验证
        public bool ValidateOperatorByAccount(string account)
        {
            if (_iOperatorRepository.GetOperatorByAccount(account) != null) return false;
            return true;
        }
        public bool ValidateOperatorByCard(string card)
        {
            if (GetOperatorByCard(card) != null) return false;
            return true;
        }

        //获取角色
        public List<RoleDbPo> GetRoles()
        {
            return _iOperatorRepository.GetRoles();
        }
        //获取员工
        public List<EmployeePo> GetEmployees()
        {
            return _iOperatorRepository.GetEmployees();
        }
    }
}
